
/****************************************************************************/

int kernelMultitaskerSignalSet(int processId, int sig, int on)
{
	// Set signal handling enabled (on) or disabled for the specified signal

	int status = 0;
	kernelProcess *signalProcess = NULL;
  
	// Make sure multitasking has been enabled
	if (!multitaskingEnabled)
		return (status = ERR_NOTINITIALIZED);

	// Make sure the signal number fits in the signal mask
	if ((sig <= 0) || (sig >= SIGNALS_MAX))
	{
		kernelError(kernel_error, "Invalid signal code %d", sig);
		return (status = ERR_RANGE);
	}

	ACQUIRE_LOCK_PROCESS_QUEUE();

	// Try to find the process
	signalProcess = getProcessById(processId);
	if (signalProcess == NULL)
	{
		// There's no such process
		RELEASE_LOCK_PROCESS_QUEUE();
		kernelError(kernel_error, "No process %d to signal", processId);
		return (status = ERR_NOSUCHPROCESS);
	}

	// If there is not yet a signal stream allocated for this process, do it now.
	if (!(signalProcess->signalStream.buffer))
	{
		status = kernelStreamNew(&(signalProcess->signalStream), 16, 1);
		if (status < 0)
		{
			RELEASE_LOCK_PROCESS_QUEUE();
			return (status);
		}
	}

	if (on)
		signalProcess->signalMask |= (1 << sig);
	else
		signalProcess->signalMask &= ~(1 << sig);

	RELEASE_LOCK_PROCESS_QUEUE();
	return (status = 0);
}

/****************************************************************************/

int kernelMultitaskerSignal(int processId, int sig)
{
	int status = 0;
	kernelProcess *signalProcess = NULL;

	// Make sure multitasking has been enabled
	if (!multitaskingEnabled)
		return (status = ERR_NOTINITIALIZED);

	// Make sure the signal number fits in the signal mask
	if ((sig <= 0) || (sig >= SIGNALS_MAX))
	{
		kernelError(kernel_error, "Invalid signal code %d", sig);
		return (status = ERR_RANGE);
	}

	ACQUIRE_LOCK_PROCESS_QUEUE();

	// Try to find the process
	signalProcess = getProcessById(processId);
	if (signalProcess == NULL)
	{
		// There's no such process
		RELEASE_LOCK_PROCESS_QUEUE();
		kernelError(kernel_error, "No process %d to signal", processId);
		return (status = ERR_NOSUCHPROCESS);
	}

	// See if the signal is handled, and make sure there's a signal stream
	if (!(signalProcess->signalMask & (1 << sig)) ||
	    !(signalProcess->signalStream.buffer))
	{
		// Not handled.  Terminate the process.
		signalProcess->state = proc_finished;
		RELEASE_LOCK_PROCESS_QUEUE();
		return (status = 0);
	}

	// Put the signal into the signal stream
	status = signalProcess->signalStream.append(&(signalProcess->signalStream), sig);

	RELEASE_LOCK_PROCESS_QUEUE();

	return (status);
}

/****************************************************************************/

int kernelMultitaskerSignalRead(int processId)
{
	int status = 0;
	kernelProcess *signalProcess = NULL;
	int sig;
  
	// Make sure multitasking has been enabled
	if (!multitaskingEnabled)
		return (status = ERR_NOTINITIALIZED);

	ACQUIRE_LOCK_PROCESS_QUEUE();

	// Try to find the process
	signalProcess = getProcessById(processId);
	if (signalProcess == NULL)
	{
		// There's no such process
		kernelError(kernel_error, "No process %d to signal", processId);
		return (status = ERR_NOSUCHPROCESS);
	}

	// Any signals handled?
	if (!(signalProcess->signalMask))
	{
		RELEASE_LOCK_PROCESS_QUEUE();
		return (status = 0);
	}

	// Make sure there's a signal stream
	if (!(signalProcess->signalStream.buffer))
	{
		RELEASE_LOCK_PROCESS_QUEUE();
		kernelError(kernel_error, "Process has no signal stream");
		return (status = ERR_NOTINITIALIZED);
	}

	if (!(signalProcess->signalStream.count))
	{
		RELEASE_LOCK_PROCESS_QUEUE();
		return (sig = 0);
	}

	status = signalProcess->signalStream.pop(&(signalProcess->signalStream), &sig);

	RELEASE_LOCK_PROCESS_QUEUE();

	if (status < 0)
		return (status);
	else
		return (sig);
}

/****************************************************************************/

